package cn.com.dhcc.ddi.datasource.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.com.dhcc.app.core.base.BaseController;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.handler.pagerhandler.Pager;
import cn.com.dhcc.app.core.handler.pagerhandler.PagerData;
import cn.com.dhcc.app.core.pubmodule.sysmgr.usermgr.service.CmUserMgrService;
import cn.com.dhcc.app.core.pubmodule.sysmgr.usermgr.vo.UserInfoVo;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.util.StrUtil;
import cn.com.dhcc.app.pub.core.tag.staticcode.StaticCode;
import cn.com.dhcc.app.pub.core.tag.staticcode.StaticCode.DB_TYPE;
import cn.com.dhcc.ddi.datamapping.service.DataMappingService;
import cn.com.dhcc.ddi.datasource.dao.DataSourceDao;
import cn.com.dhcc.ddi.datasource.service.DataSourceDBService;
import cn.com.dhcc.ddi.datasource.service.DataSourceLocalDiskService;
import cn.com.dhcc.ddi.datasource.service.DataSourceMysqlService;
import cn.com.dhcc.ddi.datasource.service.DataSourceOracleService;
import cn.com.dhcc.ddi.datasource.service.DataSourceSQLserverExtService;
import cn.com.dhcc.ddi.datasource.service.DataSourceSQLserverService;
import cn.com.dhcc.ddi.datasource.service.DataSourceService;
import cn.com.dhcc.ddi.datasource.service.TableColService;
import cn.com.dhcc.ddi.datasource.service.TableInfoService;
import cn.com.dhcc.ddi.datasource.vo.DataSourceConfVo;
import cn.com.dhcc.ddi.datasource.vo.DataSourceVo;
import cn.com.dhcc.ddi.datasource.vo.TableColVo;
import cn.com.dhcc.ddi.datasource.vo.TableInfoVo;
import cn.com.dhcc.ddi.node.service.NodeInfoService;
import cn.com.dhcc.ddi.node.vo.NodeInfo;

/**
 * 
 * @ClassName: DataSourceController
 * @Description: 数据源管理
 * @author fxx
 * @date 2016-11-14
 * 
 */
@Controller
@RequestMapping(value="/data_source")
public class DataSourceController extends BaseController {
	private static Logger logger = Log.getLogger(LOGTYPE.DDI);
	@Autowired
	DataSourceService dataSourceService;
	@Autowired
	DataSourceMysqlService dataSourceMysqlService;
	@Autowired
	DataSourceOracleService dataSourceOracleService;
	@Autowired
	DataSourceSQLserverService dataSourceSQLserverService;
	@Autowired
    DataSourceSQLserverExtService dataSourceSQLserverExtService;
	@Autowired
	DataSourceDBService dataSourceDBService;
	@Autowired
	TableInfoService tableInfoService;
	@Autowired
	TableColService tableColService;
	@Autowired
	NodeInfoService  nodeInfoService;
	@Autowired
	DataMappingService dataMappingService;
	@Autowired
	DataSourceDao dataSourceDao;
	@Autowired
	CmUserMgrService userMgrService;
	@Autowired
	DataSourceLocalDiskService localDiskService;
     
	/**
	 * 
	 * @Title: dataSourceList
	 * @Description: 获取数据源信息列表
	 * @param @param model
	 * @param @param pager
	 * @param @return 参数
	 * @return String 返回类型
	 * @throws
	 */
	@RequestMapping(value="/data_source_list")
	public String dataSourceList(Model model, Pager pager, String name, HttpSession httpSession){
		try {
			WhereCondition searchParameter = new WhereCondition();
			searchParameter.where1Eq1();
			if (StrUtil.isNotBank(name)) {
				searchParameter.and().like("t1.name", "%"+name+"%");
			}
			Boolean isAdmin = BaseController.getCurrentUserInfo(httpSession).isSuperAdmin();
			String userId = BaseController.getCurrentUserInfo(httpSession).getId();
			UserInfoVo currentUser = userMgrService.getUserById(userId);
			model.addAttribute("currentUser", currentUser);
			if (!isAdmin) {
				if (currentUser != null) {
					String nodeIdsStr = currentUser.getExt2();
					if (StrUtil.isNotBank(nodeIdsStr)) {
						String[] nodeIds = nodeIdsStr.split(",");
						searchParameter.andIn("t1.node_id", nodeIds);
					} else {
						searchParameter.andEq("1", "2");
					}
				}
			}
			searchParameter.orderBy("t1.mtime desc");
			PagerData<DataSourceVo> datas = dataSourceService.getPagerList(pager, searchParameter);
			model.addAttribute(DATA_KEY, datas.getDatas());
			setTotoal(model, datas.getTotal());
		} catch (ServiceException e) {
			logger.error("获取数据源信息列表失败", e);
			return toAlertPage(model, "获取数据源信息列表失败");
		}
		return "datasource/data_source_list";
	}
	
	/**
	 * 
	 * @Title: getDataSourceById
	 * @Description: 数据源查看
	 * @param @param model
	 * @param @param id
	 * @param @return 参数
	 * @return String 返回类型
	 * @throws
	 */
	@RequestMapping(value="/data_source_get")
	public String getDataSourceById(Model model, String id){
		try {
			DataSourceVo vo = dataSourceService.getDataSourceById(id);
			if (vo == null) {
				return toAlertPage(model, "此条数据不存在");
			}
			String dsId = vo.getId();
			List<TableInfoVo> tableInfoList = tableInfoService.getTableInfoByDsId(dsId);
			for (int i = 0; i < tableInfoList.size(); i++) {
				String tableId = tableInfoList.get(i).getId();
				List<TableColVo> tableColList = tableColService.getColsByTableId(tableId);
				tableInfoList.get(i).setTableColVos(tableColList);
			}
			model.addAttribute(VO_KEY, vo);
			model.addAttribute("tableInfoList", tableInfoList);
		} catch (ServiceException e) {
			logger.error("获取数据源详细信息失败", e);
			return toAlertPage(model, "获取数据源详细信息失败");
		}
		return "datasource/data_source_get";
	}

	/**
	 * 
	 * @Title: dataSourceAdd
	 * @Description: 新增页面
	 * @param @param model
	 * @param @return 参数
	 * @return String 返回类型
	 * @throws
	 */
	@RequestMapping(value="/data_source_add")
	public String dataSourceAdd(Model model, HttpSession httpSession){
		try {
			//获取当前用户所有节点信息
			WhereCondition whereCondition = new WhereCondition();
			Boolean isAdmin = BaseController.getCurrentUserInfo(httpSession).isSuperAdmin();
			String userId = BaseController.getCurrentUserInfo(httpSession).getId();
			UserInfoVo currentUser = userMgrService.getUserById(userId);
			if (!isAdmin) {
				if (currentUser != null) {
					String nodeIdsStr = currentUser.getExt2();
					if (StrUtil.isNotBank(nodeIdsStr)) {
						String[] nodeIds = nodeIdsStr.split(",");
						whereCondition.andIn("id", nodeIds);
					} else {
						whereCondition.andEq("1", "2");
					}
				}
			}
			List<NodeInfo> list = nodeInfoService.getAllNodeList(whereCondition);
			model.addAttribute("nodeList", list);
		} catch (Exception e) {
			logger.error("操作失败", e);
		}
		return "datasource/data_source_add";
	}
	
	/**
	 * 
	 * @Title: add
	 * @Description: 新增数据源
	 * @param @param model
	 * @param @param vo
	 * @param @param mdataType
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
	@RequestMapping(value = "/add_data_source")
	@ResponseBody
	public Map<String, Object> addDataSource(DataSourceVo vo, String tbInfoList, String tbColInfoList) {
		try {
			vo.setMtime(new Date());
			vo.setStatus(StaticCode.DATA_STATUS.ENABLE.getCode());
			dataSourceDBService.insert(vo, tbInfoList, tbColInfoList);
			return jsonSuccessResult("添加成功");
		} catch (ServiceException e) {
			logger.error("添加失败", e);
			return jsonFailResult("添加失败");
		}
	}
	
	/**
	 * 
	 * @Title: save
	 * @Description: 保存基本信息
	 * @param @param vo
	 * @param @param dbType
	 * @param @param driverName
	 * @param @param url
	 * @param @param userName
	 * @param @param password
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
	@RequestMapping(value = "/data_source_basic_info_save")
	@ResponseBody
	public Map<String, Object> saveDataSource(DataSourceVo vo, String dbType, String driverName, String url, String userName, String password) {
		try {
			DataSourceVo dataSource = getDataSourceVoByParam(dbType, driverName, url, userName, password);
			boolean isOk = dataSourceDBService.dsStatusOk(dataSource);
			if (!isOk) {
				return jsonFailResult("数据源测试不成功,请检查相关参数");
			} else {
				vo.setMtime(new Date());
				vo.setStatus(StaticCode.DATA_STATUS.ENABLE.getCode());
				dataSourceDao.updateDataSource(vo);
			}
			return jsonSuccessResult("保存成功");
		} catch (DaoException e) {
			logger.error("保存失败", e);
			return jsonFailResult("保存失败");
		}
	}
	
	/**
	 * 
	 * @Title: delete
	 * @Description: 删除数据源
	 * @param @param model
	 * @param @param id
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
	@RequestMapping(value = "/data_source_delete", method = RequestMethod.POST)
	@ResponseBody
	public Map<String, Object> deleteDataSource(Model model, String id) {
		try { 
			int count = dataMappingService.getCountByDsId(id);
			if (count == 0) {
				dataSourceService.deleteDataSource(id);
				return jsonSuccessResult("删除成功");
			} else {
				return jsonFailResult("当前数据源已关联数据映射，无法删除！");
			}
			
		} catch (Exception e) {
			logger.error("删除失败", e);
			return jsonFailResult("删除失败");
		}
	}
	
	/**
	 * 
	 * @Title: update
	 * @Description: 更新数据源页面
	 * @param @param model
	 * @param @param id
	 * @param @return 参数
	 * @return String 返回类型
	 * @throws
	 */
	@RequestMapping("/data_source_update")
	public String dataSourceUpdate(Model model, String id, HttpSession httpSession) {
		try { 
			DataSourceVo vo = dataSourceService.getDataSourceById(id);
			if (vo == null) {
				return toAlertPage(model, "此条数据不存在");
			}
			//获取表信息
			String dsId = vo.getId();
			List<TableInfoVo> tableInfoList = tableInfoService.getTableInfoByDsId(dsId);
			for (int i = 0; i < tableInfoList.size(); i++) {
				String tableId = tableInfoList.get(i).getId();
				List<TableColVo> tableColList = tableColService.getColsByTableId(tableId);
				tableInfoList.get(i).setTableColVos(tableColList);
			}
			//获取节点信息
			WhereCondition whereCondition = new WhereCondition();
			Boolean isAdmin = BaseController.getCurrentUserInfo(httpSession).isSuperAdmin();
			String userId = BaseController.getCurrentUserInfo(httpSession).getId();
			UserInfoVo currentUser = userMgrService.getUserById(userId);
			if (!isAdmin) {
				if (currentUser != null) {
					String nodeIdsStr = currentUser.getExt2();
					if (StrUtil.isNotBank(nodeIdsStr)) {
						String[] nodeIds = nodeIdsStr.split(",");
						whereCondition.andIn("id", nodeIds);
					} else {
						whereCondition.andEq("1", "2");
					}
				}
			}
			List<NodeInfo> list = nodeInfoService.getAllNodeList(whereCondition);
			//判断数据源是否可以重新抽取
			int count = dataMappingService.getCountBySrcDsId(id);
			if (count == 0) {
				model.addAttribute("ifAgainExtra", "true");
			} else {
				model.addAttribute("ifAgainExtra", "false");
			}
			model.addAttribute("nodeList", list);
			model.addAttribute(VO_KEY, vo);
			model.addAttribute("tableInfoList", tableInfoList);
			return "datasource/data_source_update";
		} catch (Exception e) {
			logger.error("操作失败", e);
			return toAlertPage(model, e.getMessage());
		}
	}
	
	/**
	 * 
	 * @Title: update
	 * @Description: 更新数据源
	 * @param @param vo
	 * @param @param tbInfoList
	 * @param @param tbColInfoList
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
	@RequestMapping(value = "/update_data_source")
	@ResponseBody
	public Map<String, Object> updateDataSource(DataSourceVo vo, String tbInfoList, String tbColInfoList) {
		try {
			vo.setMtime(new Date());
			vo.setStatus(StaticCode.DATA_STATUS.ENABLE.getCode());
			dataSourceDBService.update(vo, tbInfoList, tbColInfoList);			
			return jsonSuccessResult("修改成功");
		} catch (ServiceException e) {
			logger.error("修改失败", e);
			return jsonFailResult("修改失败");
		}
	}

	/**
	 * 
	 * @Title: dsStatusOk
	 * @Description: 测试数据库连接状态
	 * @param @param request
	 * @param @param dataSource
	 * @param @param dbType
	 * @param @param driverName
	 * @param @param url
	 * @param @param userName
	 * @param @param password
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
   @RequestMapping(value="/data_source_test", method = RequestMethod.POST)
   @ResponseBody
   public Map<String, Object> dsStatusOk(HttpServletRequest request, DataSourceVo dataSource, String dbType, String driverName, String url, String userName, String password){
	   String msg = "";
	   try{
		   dataSource = getDataSourceVoByParam(dbType, driverName, url, userName, password);
		   boolean isOk = dataSourceDBService.dsStatusOk(dataSource);
		   if (!isOk) {
			   return jsonFailResult("数据源测试不成功,请检查相关参数");
		   } else {
			   return jsonSuccessResult("测试成功");
		   }
	   } catch (Exception e) {
			msg = "数据源测试不成功,请检查相关参数";
			logger.error(msg, e);
			return jsonFailResult(msg);
	   }
   }
   
	/**
	 * 
	 * @Title: extractMetadata
	 * @Description: 抽取元数据
	 * @param @param model
	 * @param @param vo
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
   @RequestMapping(value="/extract_meta_data")
   @ResponseBody
   public Map<String, Object> extractMetadata(Model model, DataSourceVo dataSource, String dbType, String driverName, String url, String userName, String password){
	   String msg = "";
	   try {
		    dataSource = getDataSourceVoByParam(dbType, driverName, url, userName, password);
			boolean isOk = dataSourceDBService.dsStatusOk(dataSource);
			List<TableInfoVo> tablelist = new ArrayList<TableInfoVo>();
			if (isOk) {
				if (dataSource.getDataSourceConfVo().getDbType().equals(DB_TYPE.ORACLE.getCode())) {
					 tablelist = dataSourceOracleService.getUserTableForOracle(dataSource);
				} else if (dataSource.getDataSourceConfVo().getDbType().equals(DB_TYPE.MYSQL.getCode())) {
					tablelist = dataSourceMysqlService.getUserTableForMysql(dataSource);
				} else if (dataSource.getDataSourceConfVo().getDbType().equals(DB_TYPE.SQLSERVER.getCode())) {
					tablelist = dataSourceSQLserverService.getUserTableForSqlserver(dataSource);
				} else if (dataSource.getDataSourceConfVo().getDbType().equals(DB_TYPE.SQLSERVEREXT.getCode())) {
				    tablelist = dataSourceSQLserverExtService.getUserTable(dataSource);
				}
			} else {
				return jsonFailResult("数据源无法连接，请检查连接信息");
			}
			msg = "抽取元数据成功";
			return jsonSuccessDataResult(msg,tablelist);
		} catch (Exception e) {
			msg = "抽取元数据失败";
			logger.error(msg, e);
			return jsonFailResult(msg);
		}
   } 

	/**
	 * 
	 * @Title: lock
	 * @Description: 停用
	 * @param @param id
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
    @RequestMapping(value="/lock_data_source")
	@ResponseBody
	public Map<String, Object> lockDataSource(String id){
		String status = StaticCode.DATA_STATUS.DISABLE.getCode();
		try {
			DataSourceVo obj = dataSourceService.getDataSourceById(id);
			if (obj == null) {
				return jsonFailResult("此条数据不存在"); 
			}
			obj.setStatus(status);
			obj.setMtime(new Date());
			dataSourceService.update(obj);
			return jsonSuccessResult("停用成功");
		} catch (ServiceException e) {
			logger.error("停用失败", e);
			return jsonFailResult("停用失败");
		}
	}
	
	/**
	 * 
	 * @Title: unlock
	 * @Description: 启用
	 * @param @param id
	 * @param @return 参数
	 * @return Map<String,Object> 返回类型
	 * @throws
	 */
	@RequestMapping(value="/unlock_data_source")
	@ResponseBody
	public Map<String, Object> unlockDataSource(String id){
		String status = StaticCode.DATA_STATUS.ENABLE.getCode();
		try {
			DataSourceVo obj = dataSourceService.getDataSourceById(id);
			if (obj == null) {
				return jsonFailResult("此条数据不存在"); 
			}
			obj.setStatus(status);
			obj.setMtime(new Date());
			dataSourceService.update(obj);
			return jsonSuccessResult("启用成功");
		} catch (ServiceException e) {
			logger.error("启用失败", e);
			return jsonFailResult("启用失败");
		}
	}
	
	/**
	 * 名称唯一性
	 * 
	 * @param newValue
	 * @param oldValue
	 * @return
	 */
	@RequestMapping("/is_dsName_unique")
	@ResponseBody
	public String isDsNameUnique(@RequestParam("name") String newValue, @RequestParam("oldValue") String oldValue, HttpSession httpSession) {
		try {

			if (dataSourceService.isPropertyUnique("name", newValue, oldValue, httpSession)) {
				return FORM_CHECK_SUCCESS;
			} else {
				return FORM_CHECK_FAIL;
			}
		} catch (Exception e) {
			return FORM_CHECK_FAIL;
		}
	}
	
	/**
	 * 
	 * @MethodName: [isLocalDiskOk]
	 * @Description:[判断磁盘目录是否存在]
	 * @Author:     [fxx]
	 * @CreateDate: [2017-5-16]
	 * @Params:     [ParamType ParamValue,ParamType ParamValue...]
	 * @See         [Related classes and methods]
	 * @Since       [Product template version]  
	 * @Return:     [String]
	 * @Throws:     [Exception]
	 *
	 */
	@RequestMapping("/is_local_disk_exists")
	@ResponseBody
	public String isLocalDiskOk(@RequestParam("dataSourceConfVo.diskDirectory") String diskDirectory){
		try {
			if (localDiskService.isLocalDiskOk(diskDirectory)) {
				return FORM_CHECK_SUCCESS;
			} else {
				return FORM_CHECK_FAIL;
			}
		} catch (Exception e) {
			return FORM_CHECK_FAIL;
		}
	}
   
	/**
	 * 
	 * @MethodName: [getDataSourceVoByParam]
	 * @Description:[获取数据源对象]
	 * @Author:     [fxx]
	 * @CreateDate: [2017-5-16]
	 * @Params:     [ParamType ParamValue,ParamType ParamValue...]
	 * @See         [Related classes and methods]
	 * @Since       [Product template version]  
	 * @Return:     [DataSourceVo]
	 * @Throws:     [Exception]
	 *
	 */
   public DataSourceVo getDataSourceVoByParam(String dbType, String driverName, String url, String userName, String password){
	   DataSourceVo dataSource = new DataSourceVo();
	   DataSourceConfVo dataSourceConfVo = new DataSourceConfVo();
	   dataSourceConfVo.setDbType(dbType);
	   dataSourceConfVo.setDriverName(driverName);
	   dataSourceConfVo.setUrl(url);
	   dataSourceConfVo.setUserName(userName);
	   dataSourceConfVo.setPassword(password);
	   dataSource.setDataSourceConfVo(dataSourceConfVo);
	   return dataSource;
   }
}
